#pragma once

#include "hdmap/HDMapExports.hpp"
#include "hdmap/HDMapCommon.hpp"

namespace Navinfo
{
	namespace Engine
	{
		
		/**
		 *	@brief Speed limit condition, range and value for road or lane
		 */
		class HDMAP_API_PUBLIC HDMapSpeedLimit
		{
		public:
			/**
			 *  @brief Construction function
			 */
			HDMapSpeedLimit(const HDMapGeometryRangeReference& rangeReference, uint16_t nSpeedLimit,
				HDMapDirection ePositiveDirection, uint16_t vehicleTypes, uint16_t dependentTypes,
				uint16_t nConditionSpeedLimit, uint16_t minSpeedLimit);
			HDMapSpeedLimit() = default;
			/**
			 *  @brief destruction function
			 */
			virtual ~HDMapSpeedLimit() = default;
		public:
			
			/**
			 *  @brief get the speedlimit value on road geometry
			 */
			const uint16_t GetSpeedLimit() const { return m_nSpeedLimit; }

			/**
			 *  @brief get the minspeedlimit value on road geometry
			 */
			const uint16_t GetMinSpeedLimit() const { return m_nMinSpeedLimit; }

			/**
			 *  @brief get the condition speedlimit value on road geometry when GetDependentType()!=0
			 */
			const uint16_t GetConditionSpeedLimit() const { return m_nConditionSpeedLimit; }

			/**
			 *  @brief get the speedlimit PositiveDirection on road geometry 
			 *		  Positive direction (true) means from start simple intersection to end simple intersection. Negative direction (false) means from end simple intersection to start simple intersection.
			 */
			const HDMapDirection GetPositiveDirection() const { return m_ePositiveDirection; }

			/**
			 *  @brief get reference info of the speed limit data
			 */
			const HDMapGeometryRangeReference& GetRangeReference() const { return mRangeReference; }

			/**
			 *  @brief get speed limit value for vehicle type
			 */
			const uint16_t GetSpeedLimitByType(HDMapVehicleTypes vehicleType, HDMapDependentType dependedtType)
			{
				if (dependedtType == HDMapDependentType::NO_DEPENDEDT_TYPE && m_nDependentTypes != 0){
					return GetSpeedLimit();
				}

				if (m_nVehicleTypes == 0 && ((m_nDependentTypes) >> (uint16_t(dependedtType)) & 1) == 1){
					return GetConditionSpeedLimit();
				}

				if (((m_nVehicleTypes) >> (uint16_t(vehicleType)) & 1) == 1)
				{
					if (m_nDependentTypes == 0){
						return GetConditionSpeedLimit();
					}
					else if(((m_nDependentTypes) >> (uint16_t(dependedtType)) & 1) == 1){
						return GetConditionSpeedLimit();
					}
				}

				return GetSpeedLimit();
			}
		private:
			/**
			 *  @brief get the speedlimit dependent type on road geometry
			 *		  Each bit from right to left represents a dependent type. see HDMapDependentType
			 */
			const uint16_t GetDependentType() const { return m_nDependentTypes; }

			/**
			 *  @brief get the speedlimit vehicle Type on road geometry
			 *         Each bit from right to left represents a vehicle type. see HDMapVehicleTypes
			 */
			const uint16_t GetVehicleType() const { return m_nVehicleTypes; }
		private:

			uint16_t					m_nSpeedLimit;
			uint16_t					m_nMinSpeedLimit;

			uint16_t					m_nDependentTypes;
			uint16_t					m_nVehicleTypes;
			uint16_t					m_nConditionSpeedLimit;

			HDMapDirection				m_ePositiveDirection;

			HDMapGeometryRangeReference	mRangeReference;

		};
	}
}